﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows;
using System.Windows.Input;

using Faust.Andrew.MTG.Helper;
using System.Reflection;

namespace Faust.Andrew.MTG
{
    public class DragDropManager
    {
        protected Point _dragStartPoint;
        protected Point _relativeStartPoint;
        protected bool _isDragging;
        protected bool _isRightDragging;
        protected FrameworkElement _sourceHost;
        protected FrameworkElement _dragElement;
        protected Cursor _dragCursor;

        public void PreviewMouseLeftButtonDown(FrameworkElement element, MouseButtonEventArgs e, bool consumeEvent)
        {
            PreviewMouseButtonDown(element, e, consumeEvent, false);
        }

        protected void PreviewMouseButtonDown(FrameworkElement element, MouseButtonEventArgs e, bool consumeEvent, bool isRightMouseButton)
        {            
            System.Diagnostics.Trace.WriteLine("PreviewMouseButtonDown");
            e.Handled = consumeEvent;
            _dragElement = null;
            _dragCursor = null;
            _isRightDragging = isRightMouseButton;
            _dragStartPoint = e.GetPosition(null);
            _relativeStartPoint = e.GetPosition(element);
        }

        public void PreviewMouseMove(FrameworkElement element, MouseEventArgs e, FrameworkElement sourceHost)
        {
            if ((e.LeftButton == MouseButtonState.Pressed || e.RightButton == MouseButtonState.Pressed) && !_isDragging)
            {
                System.Diagnostics.Trace.WriteLine("PreviewMouseMove");
                Point position = e.GetPosition(null);

                if (Math.Abs(position.X - _dragStartPoint.X) > SystemParameters.MinimumHorizontalDragDistance ||
                    Math.Abs(position.Y - _dragStartPoint.Y) > SystemParameters.MinimumVerticalDragDistance)
                {
                    StartDrag(element, e, sourceHost);
                }
            }
        }

        protected void StartDrag(FrameworkElement element, MouseEventArgs e, FrameworkElement sourceHost)
        {
            if (element.DataContext is Card)
            {
                Card card = (Card)element.DataContext;
                StartCardDrag(element, e, sourceHost, card);
                e.Handled = true;
            }
            else if (element.DataContext is DeckCard)
            {
                Card card = (element.DataContext as DeckCard).Card;
                StartCardDrag(element, e, sourceHost, card);
                e.Handled = true;
            }            

            //if (element.DataContext is Card || element.DataContext is DeckCard)
            //{
            //    StartCardDrag(element, e, sourceHost);
            //}            
            
            
        }

        private void StartCardDrag(FrameworkElement element, MouseEventArgs e, FrameworkElement sourceHost, Card card)
        {
            System.Diagnostics.Trace.WriteLine("Card Drag");                                              
            DataObject data = GetDataObject(card);
            _dragCursor = CursorHelper.CreateCursor(element, 1.0, 1.0);
            StartDrag(data, element, e, sourceHost);

        }

        protected void StartDrag(DataObject data, FrameworkElement element, MouseEventArgs e, FrameworkElement sourceHost)
        {
            _isDragging = true;

            _sourceHost = sourceHost;
            _dragElement = element;

            sourceHost.GiveFeedback += Source_GiveFeedback;

            DragDrop.AddQueryContinueDragHandler(sourceHost, QueryContinueDragEvent);
            DragDrop.DoDragDrop(sourceHost, data, DragDropEffects.Move);

            sourceHost.GiveFeedback -= Source_GiveFeedback;

            _isDragging = false;
        }

        void Source_GiveFeedback(object sender, GiveFeedbackEventArgs e)
        {
            if (_dragCursor != null)
            {
                Mouse.SetCursor(_dragCursor);
                e.UseDefaultCursors = false;
                e.Handled = true;
            }
        }

        private void QueryContinueDragEvent(object sender, QueryContinueDragEventArgs e)
        {
            e.Handled = true;

            if (e.EscapePressed)
            {
                e.Action = DragAction.Cancel;
                return;
            }

            e.Action = DragAction.Drop;

            if ((e.KeyStates & DragDropKeyStates.LeftMouseButton) != DragDropKeyStates.None)
            {
                // Still dragging with Left Mouse Button
                e.Action = DragAction.Continue;
            }
            else if ((e.KeyStates & DragDropKeyStates.RightMouseButton) != DragDropKeyStates.None)
            {
                // Still dragging with Right Mouse Button
                e.Action = DragAction.Continue;
            }
        }

        protected DataObject GetDataObject(object element)
        {
            return new DataObject(element.GetType(), element);            
        }
    }
}
